Migo商城2.0 商品详情页面的实现 二十一

Migo商城2.0 商品详情页面的实现 二十一

分析:

正常来说,这块是可以单独拿出来做一个系统,然后进行页面静态化,提高响应速度,这里就不做那么麻烦了,直接找后台管理系统这里对外提供web服务,页面静态化以后有时间再做,反正也没多少技术含量

我们打开一个商品的链接,大概是如下的形式:

http://www.migo.com/item/{itemId}.html

从上图应该就可以看到jd商品详情页面应该是一个单独的工程,后面直接跟了商品的id,好了,分析完毕,开搞代码:

如图:

通过商品id查询商品,返回数据加入modelAndView

portal系统中导入POJO

注意点如图:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
package com.migo.portal.pojo;



import org.apache.commons.lang3.StringUtils;

import java.util.Date;


public class Item {


private Long id;

private String title;

private String sellPoint;

private Long price;

private Integer num;

private String barcode;

private String image;

private Long cid;

private Integer status;
private Date created;
private Date updated;

public String[] getImages(){
return StringUtils.split(this.getImage(),",");
}

public Date getCreated() {
return created;
}

public void setCreated(Date created) {
this.created = created;
}

public Date getUpdated() {
return updated;
}

public void setUpdated(Date updated) {
this.updated = updated;
}

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public String getTitle() {
return title;
}

public void setTitle(String title) {
this.title = title;
}

public String getSellPoint() {
return sellPoint;
}

public void setSellPoint(String sellPoint) {
this.sellPoint = sellPoint;
}

public Long getPrice() {
return price;
}

public void setPrice(Long price) {
this.price = price;
}

public Integer getNum() {
return num;
}

public void setNum(Integer num) {
this.num = num;
}

public String getBarcode() {
return barcode;
}

public void setBarcode(String barcode) {
this.barcode = barcode;
}

public String getImage() {
return image;
}

public void setImage(String image) {
this.image = image;
}

public Long getCid() {
return cid;
}

public void setCid(Long cid) {
this.cid = cid;
}

public Integer getStatus() {
return status;
}

public void setStatus(Integer status) {
this.status = status;
}



@Override
public String toString() {
return "Item [id=" + id + ", title=" + title + ", sellPoint=" + sellPoint + ", price=" + price
+ ", num=" + num + ", barcode=" + barcode + ", image=" + image + ", cid=" + cid + ", status="
+ status + "]";
}

}

controller代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package com.migo.portal.controller;

import com.migo.portal.pojo.Item;
import com.migo.portal.service.ItemService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

/**
* Author 知秋
* Created by kauw on 2016/12/9.
*/
@Controller
@RequestMapping("item")
public class ItemController {
@Autowired
private ItemService itemService;


@RequestMapping(value = "{itemId}",method = RequestMethod.GET)
public String getItem(Model model, @PathVariable(value = "itemId") Long itemId){
Item item=this.itemService.queryItemByItemId(itemId);
model.addAttribute("item",item);
return "item";
}
}

service代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package com.migo.portal.service;

import com.migo.portal.pojo.Item;
import com.migo.utils.HttpClientUtil;
import com.migo.utils.JsonUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

/**
* Author 知秋
* Created by kauw on 2016/12/9.
*/
@Service
public class ItemService {
@Value("${MIGO_MANAGE_URL}")
private String MIGO_MANAGE_URL;
public Item queryItemByItemId(Long itemId) {

try {
String URL=MIGO_MANAGE_URL+"/rest/webs/item/"+itemId;
String doGetJsonData = HttpClientUtil.doGet(URL);
return JsonUtils.jsonToPojo(doGetJsonData,Item.class);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}

manage系统提供接口服务:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
package com.migo.controller.webs;

import com.migo.pojo.Item;
import com.migo.service.ItemService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

/**
* Author 知秋
* Created by kauw on 2016/12/9.
*/
@Controller
@RequestMapping("webs/item")
public class WebsItemController {
private static final Logger logger= LoggerFactory.getLogger(WebsItemController.class);
@Autowired
private ItemService itemService;

@RequestMapping(value = "{itemId}",method = RequestMethod.GET)
public ResponseEntity<Item> queryByItemId(@PathVariable("itemId") Long itemId){
try {
if (logger.isInfoEnabled()){
logger.info("根据itemId查询商品详情 itemId = {}",itemId);
}
Item item = this.itemService.queryById(itemId);
if (null==item){
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null);
}
return ResponseEntity.ok(item);
} catch (Exception e) {
logger.error("根据itemId查询商品详情出错,服务器傲娇了 itemId = {}",itemId,e);

}
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null);
}
}

测试结果:

添加商品描述:

portal工程controller model加入itemDesc属性

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package com.migo.portal.controller;

import com.migo.portal.pojo.Item;
import com.migo.portal.pojo.ItemDesc;
import com.migo.portal.service.ItemService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

/**
* Author 知秋
* Created by kauw on 2016/12/9.
*/
@Controller
@RequestMapping("item")
public class ItemController {
@Autowired
private ItemService itemService;


@RequestMapping(value = "{itemId}",method = RequestMethod.GET)
public String getItem(Model model, @PathVariable(value = "itemId") Long itemId){
Item item=this.itemService.queryItemByItemId(itemId);
model.addAttribute("item",item);
ItemDesc itemDesc=this.itemService.queryItemDescByItemId(itemId);
model.addAttribute("itemDesc",itemDesc);
return "item";
}
}

service实现

1
2
3
4
5
6
7
8
9
10

public ItemDesc queryItemDescByItemId(Long itemId) {
try {
String URL=MIGO_MANAGE_URL+"/rest/webs/item/desc/"+itemId;
String doGetJsonData = HttpClientUtil.doGet(URL);
return JsonUtils.jsonToPojo(doGetJsonData,ItemDesc.class);
} catch (Exception e) {
e.printStackTrace();
}
return null;

manage系统提供相应接口服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/**
* 根据itemId查询商品描述
* @param itemId
* @return
*/
@RequestMapping(value = "/desc/{itemId}",method = RequestMethod.GET)
public ResponseEntity<ItemDesc> queryDescByitemId(@PathVariable("itemId") Long itemId){

try {
if (logger.isInfoEnabled()){
logger.info("根据itemId查询商品描述 itemId = {}",itemId);
}
ItemDesc itemDesc = this.itemDescService.queryById(itemId);
if (null==itemDesc) {
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null);
}
return ResponseEntity.ok(itemDesc);
} catch (Exception e) {
logger.error("根据itemId查询商品描述出错,服务器傲娇了 itemId = {}",itemId,e);
}
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null);
}

测试结果:

显示商品规格参数

portal工程controller model加入itemParam属性

controller代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package com.migo.portal.controller;

import com.migo.portal.pojo.Item;
import com.migo.portal.pojo.ItemDesc;
import com.migo.portal.service.ItemService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

/**
* Author 知秋
* Created by kauw on 2016/12/9.
*/
@Controller
@RequestMapping("item")
public class ItemController {
@Autowired
private ItemService itemService;


@RequestMapping(value = "{itemId}",method = RequestMethod.GET)
public String getItem(Model model, @PathVariable(value = "itemId") Long itemId){
Item item=this.itemService.queryItemByItemId(itemId);
model.addAttribute("item",item);
ItemDesc itemDesc=this.itemService.queryItemDescByItemId(itemId);
model.addAttribute("itemDesc",itemDesc);
String itemParamItem=this.itemService.queryItemParamItemByItemId(itemId);
model.addAttribute("itemParam",itemParamItem);
return "item";
}
}

如此图所示,得到itemParam后直接显示,那么需要对得到数据里面参数做页面格式化:

所以service代码为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public String queryItemParamItemByItemId(Long itemId) {
try {
String URL=MIGO_MANAGE_URL+"/rest/webs/item/paramitem/"+itemId;
String doGetJsonData = HttpClientUtil.doGet(URL);
ItemParamItem itemParamItem = JsonUtils.jsonToPojo(doGetJsonData, ItemParamItem.class);
String paramData = itemParamItem.getParamData();
ArrayNode arrayNode = (ArrayNode) MAPPER.readTree(paramData);
StringBuilder sb = new StringBuilder();
sb.append("<table cellpadding=\"0\" cellspacing=\"1\" width=\"100%\" border=\"0\" class=\"Ptable\"><tbody>");
for (JsonNode param : arrayNode) {
sb.append("<tr><th class=\"tdTitle\" colspan=\"2\">" + param.get("group").asText()
+ "</th></tr>");
ArrayNode params = (ArrayNode) param.get("params");
for (JsonNode p : params) {
sb.append("<tr><td class=\"tdTitle\">" + p.get("k").asText() + "</td><td>"
+ p.get("v").asText() + "</td></tr>");
}
}
sb.append("</tbody></table>");

return sb.toString();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}

manage系统提供服务接口:

controller代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/**
* 根据itemId查询商品规格参数
* @param itemId
* @return
*/
@RequestMapping(value = "/paramitem/{itemId}",method = RequestMethod.GET)
public ResponseEntity<ItemParamItem> queryItemParamItemByitemId(
@PathVariable("itemId") Long itemId){
try {
if (logger.isInfoEnabled()){
logger.info("根据itemId查询商品规格参数 itemId = {}",itemId);
}
ItemParamItem itemParamItem = this.itemParamItemService.queryByIdse(itemId);
if (itemParamItem==null){
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null);
}
return ResponseEntity.ok(itemParamItem);
} catch (Exception e) {
logger.error("根据itemId查询商品规格参数出错,服务器傲娇了 itemId = {}",itemId,e);
}
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null);
}

service代码:

1
2
3
4
5
6
7
8
9
10
11
/**
* 根据商品id查询商品规格参数数据
* @param itemId
* @return
*/
public ItemParamItem queryByIdse(Long itemId) {
ItemParamItem example=new ItemParamItem();
example.setItemId(itemId);

return this.itemParamItemMapper.select(example).get(0);
}

测试得到结果:

portal和后端manage系统中相应service中加入缓存逻辑:

portal端添加逻辑代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
package com.migo.portal.service;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.migo.portal.pojo.Item;
import com.migo.portal.pojo.ItemDesc;
import com.migo.portal.pojo.ItemParamItem;
import com.migo.service.JedisClient;
import com.migo.utils.HttpClientUtil;
import com.migo.utils.JsonUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

/**
* Author 知秋
* Created by kauw on 2016/12/9.
*/
@Service
public class ItemService {
private static final ObjectMapper MAPPER = new ObjectMapper();
@Autowired
private JedisClient jedisClient;

private static final String REDIS_KEY = "MIGO_PORTAL";


private static final Integer REDIS_TIME = 60 * 60 * 24 * 30;
@Value("${MIGO_MANAGE_URL}")
private String MIGO_MANAGE_URL;
public Item queryItemByItemId(Long itemId) {

//添加缓存逻辑
String key=REDIS_KEY+":"+itemId+":ITEM_DETAIL";
try {

String redisJsonData = jedisClient.get(key);
if (StringUtils.isNotEmpty(redisJsonData)){
return JsonUtils.jsonToPojo(redisJsonData,Item.class);
}
} catch (Exception e) {
e.printStackTrace();
}

//正常业务逻辑
try {
String URL=MIGO_MANAGE_URL+"/rest/webs/item/"+itemId;
String doGetJsonData = HttpClientUtil.doGet(URL);
//将数据写入缓存中
try {
jedisClient.set(key,doGetJsonData,REDIS_TIME);
} catch (Exception e) {
e.printStackTrace();
}

return JsonUtils.jsonToPojo(doGetJsonData,Item.class);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}

public ItemDesc queryItemDescByItemId(Long itemId) {
//添加缓存逻辑
String key=REDIS_KEY+":"+itemId+":ITEM_DESC";
try {

String redisJsonData = jedisClient.get(key);
if (StringUtils.isNotEmpty(redisJsonData)){
return JsonUtils.jsonToPojo(redisJsonData,ItemDesc.class);
}
} catch (Exception e) {
e.printStackTrace();
}

try {
String URL=MIGO_MANAGE_URL+"/rest/webs/item/desc/"+itemId;
String doGetJsonData = HttpClientUtil.doGet(URL);

//将数据写入缓存中
try {
jedisClient.set(key,doGetJsonData,REDIS_TIME);
} catch (Exception e) {
e.printStackTrace();
}

return JsonUtils.jsonToPojo(doGetJsonData,ItemDesc.class);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}

public String queryItemParamItemByItemId(Long itemId) {
//添加缓存逻辑
String key=REDIS_KEY+":"+itemId+":ITEM_PARAM_ITEM";
try {
String redisJsonData = jedisClient.get(key);
if (StringUtils.isNotEmpty(redisJsonData)){
return redisJsonData;
}
} catch (Exception e) {
e.printStackTrace();
}
try {
String URL=MIGO_MANAGE_URL+"/rest/webs/item/paramitem/"+itemId;
String doGetJsonData = HttpClientUtil.doGet(URL);
ItemParamItem itemParamItem = JsonUtils.jsonToPojo(doGetJsonData, ItemParamItem.class);
String paramData = itemParamItem.getParamData();
ArrayNode arrayNode = (ArrayNode) MAPPER.readTree(paramData);
StringBuilder sb = new StringBuilder();
sb.append("<table cellpadding=\"0\" cellspacing=\"1\" width=\"100%\" border=\"0\" class=\"Ptable\"><tbody>");
for (JsonNode param : arrayNode) {
sb.append("<tr><th class=\"tdTitle\" colspan=\"2\">" + param.get("group").asText()
+ "</th></tr>");
ArrayNode params = (ArrayNode) param.get("params");
for (JsonNode p : params) {
sb.append("<tr><td class=\"tdTitle\">" + p.get("k").asText() + "</td><td>"
+ p.get("v").asText() + "</td></tr>");
}
}
sb.append("</tbody></table>");

//将数据写入缓存中
try {
jedisClient.set(key,sb.toString(),REDIS_TIME);
} catch (Exception e) {
e.printStackTrace();
}

return sb.toString();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}

manage端添加缓存代码:

ItemService

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public Item queryByIdse(Long itemId) {
String key=REDIS_KEY+":"+itemId+ITEM_DETAIL_KEY;
//添加缓存逻辑
try {
String jsonData = jedisClient.get(key);
if (StringUtils.isNotEmpty(jsonData)){
return JsonUtils.jsonToPojo(jsonData,Item.class);
}
} catch (Exception e) {
e.printStackTrace();
}


Item item = super.queryById(itemId);

//数据加入缓存
try {
jedisClient.set(key,JsonUtils.objectToJson(item),REDIS_TIME);
} catch (Exception e) {
e.printStackTrace();
}
return item;
}

ItemParamItemService

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/**
* 根据商品id查询商品规格参数数据
* @param itemId
* @return
*/
public ItemParamItem queryByIdse(Long itemId) {
//添加缓存逻辑
String key=REDIS_KEY+":"+itemId+ITEM_PARAM_KEY;
try {
String s = jedisClient.get(key);
if (StringUtils.isNotEmpty(s)){
return JsonUtils.jsonToPojo(s,ItemParamItem.class);
}
} catch (Exception e) {
e.printStackTrace();
}


ItemParamItem example=new ItemParamItem();
example.setItemId(itemId);

ItemParamItem itemParamItem = this.itemParamItemMapper.select(example).get(0);

//加入缓存
try {
jedisClient.set(key,JsonUtils.objectToJson(itemParamItem),REDIS_TIME);
} catch (Exception e) {
e.printStackTrace();
}
return itemParamItem;
}

ItemDescService

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
package com.migo.service;

import com.migo.pojo.ItemDesc;
import com.migo.utils.JsonUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

/**
* Author 知秋
* Created by kauw on 2016/11/12.
*/
@Service
public class ItemDescService extends BaseService<ItemDesc> {
@Value("${REDIS_KEY}")
private String REDIS_KEY;
@Value("${REDIS_TIME}")
private Integer REDIS_TIME;
private static final String ITEM_DESC_KEY = ":ITEM_DESC";

@Autowired
private JedisClient jedisClient;

public ItemDesc queryByIdse(Long itemId) {
//加入缓存逻辑
String key=REDIS_KEY+":"+itemId+ITEM_DESC_KEY;
try {
String jsonData = jedisClient.get(key);
if (StringUtils.isNotEmpty(jsonData)){
return JsonUtils.jsonToPojo(jsonData,ItemDesc.class);
}
} catch (Exception e) {
e.printStackTrace();
}

ItemDesc itemDesc = super.queryById(itemId);

//数据添加到缓存中
try {
jedisClient.set(key,JsonUtils.objectToJson(itemDesc),REDIS_TIME);
} catch (Exception e) {
e.printStackTrace();
}
return itemDesc;
}
}

关于两个系统间缓存同步问题会在后面通过消息中间件处理,这里就不添加临时解决方案了

上面的代码其实还有进一步 的优化方法,这里留给读者思考了,又搞到凌晨1点多了,睡觉!

您的支持将鼓励我继续创作!